// 1. 支持往不同的地方输出日志 (现实往文件输出)
// 2. 日志分级别
//    1. Debug
//    2. Trace
//    3. Info
//    4. Warning
//    5. Error
//    6. Fatal
// 3. 日志要支持开关控制，比如说开发的时候什么级别都能输出，但是上线之后只有INFO级别往下的才能输出
// 4. 完整的日志记录要包含有时间、行号、文件名、日志级别、日志信息
// 5. 日志文件要切割
//    1. 按文件大小切割（不实现）
//       1. 每次记录日志之前都判断一下当前写的这个文件的文件大小
//    2. 按日期切割
//       1. 在日志结构体中设置一个字段记录上一次切割的小时数
//       2. 在写日志之前检查一下当前时间的小时数和之前保存的是否一致，不一致就要切割

package main

import (
	"fmt"
	"os"
	"path"
	"runtime"
	"strings"
	"time"
)

//Logging 结构体
type Logging struct {
	logName string
}

func newLogging(logName string) *Logging {
	return &Logging{
		logName: logName,
	}
}

func (l *Logging) log(a interface{}, funcName string, fileName string, line int) {
	now := time.Now().Format("2006-01-02")
	file, err := os.OpenFile(now, os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)
	if err != nil {
		fmt.Println("写入文件错误！")
		return
	}
	defer file.Close()
	strList := []string{"debug", "trace", "info", "warning", "error", "fatal"}
	newLogName := strings.ToLower(l.logName)
	str, ok := a.(string)
	if ok {
		switch newLogName {
		case "debug":
			for i := 0; i < len(strList); i++ {
				fmt.Fprintf(file, "[文件%v][模块%v][行数%v][级别%v]:%s\n", fileName, funcName, line, strList[i], str)
			}
		case "trace":

			for i := 0; i < len(strList[1:]); i++ {
				fmt.Fprintf(file, "[文件%v][模块%v][行数%v][级别%v]:%s\n", fileName, funcName, line, strList[i], str)
			}
		case "info":
			for i := 0; i < len(strList[2:]); i++ {
				fmt.Fprintf(file, "[文件%v][模块%v][行数%v][级别%v]:%s\n", fileName, funcName, line, strList[i], str)
			}
		case "warning":
			for i := 0; i < len(strList[3:]); i++ {
				fmt.Fprintf(file, "[文件%v][模块%v][行数%v][级别%v]:%s\n", fileName, funcName, line, strList[i], str)
			}
		case "error":
			for i := 0; i < len(strList[4:]); i++ {
				fmt.Fprintf(file, "[文件%v][模块%v][行数%v][级别%v]:%s\n", fileName, funcName, line, strList[i], str)
			}
		case "fatal":
			fmt.Fprintf(file, "[文件%v][模块%v][行数%v][fatal]:%s\n", fileName, funcName, line, str)
		default:
			fmt.Println("未定义的错误级别!")
		}
	} else {
		fmt.Println("传入的必须是字符串！")
	}

}

func getInfo(skip int) (funcName, fileName string, lineNo int) {
	pc, file, lineNo, ok := runtime.Caller(skip)
	if !ok {
		fmt.Printf("runtime.Caller() failed\n")
		return
	}
	funcName = runtime.FuncForPC(pc).Name()
	fileName = path.Base(file)
	funcName = strings.Split(funcName, ".")[1]
	return
}

func main() {

	log := newLogging("debug")
	for {
		funcName, fileName, line := getInfo(1)
		log.log("记录一下日志", funcName, fileName, line)

		time.Sleep(time.Duration(2) * time.Second)

	}

}
